package com.heima.comment.service.impl;
import java.math.BigDecimal;
import java.util.*;

import com.heima.comment.feign.UserFeign;
import com.heima.comment.service.CommentService;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private UserFeign userFeign;
    @Autowired
    private MongoTemplate mongoTemplate;

    @Resource(name="likesLock")
    RLock rLock;


    @Override
    public ResponseResult findByArticleId(CommentDto dto) {


        if (dto==null||dto.getArticleId()==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        if (dto.getMinDate()==null)
            dto.setMinDate(new Date());
        int size = 20;
        Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate()))
                            .with(Sort.by(Sort.Direction.DESC,"CreatedTime")).limit(size);
        List<ApComment> commentList = mongoTemplate.find(query, ApComment.class);
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null||user.getId()==null)
            return ResponseResult.okResult(commentList);
        List<String> commentIds = commentList.stream().map(ApComment::getId).collect(Collectors.toList());

        Query myLikeCommentQuery = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").in(commentIds));
        List<ApCommentLike> myLikeCommentList = mongoTemplate.find(myLikeCommentQuery, ApCommentLike.class);
        if (myLikeCommentList.isEmpty())
            return ResponseResult.okResult(commentList);
        Set<String> set = myLikeCommentList.stream().map(ApCommentLike::getCommentId).collect(Collectors.toSet());
        List<ApCommentVo> list = commentList.stream().map(comment -> {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(comment, apCommentVo);
            if (set.contains(apCommentVo.getId()))
                apCommentVo.setOperation((short) 0);
            return apCommentVo;
        }).collect(Collectors.toList());
        return ResponseResult.okResult(list);
    }

    @Override
    public ResponseResult like(CommentLikeDto dto) {

        if (dto==null || dto.getCommentId()==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        if (dto.getOperation()==null || (dto.getOperation()!=0 && dto.getOperation()!=1))
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);

        rLock.lock();


        ApComment apComment;
        try {
            apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            if (apComment==null)
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"评论不存在");


            if (dto.getOperation()==0) {
                ApCommentLike apCommentLike = new ApCommentLike();
                apCommentLike.setAuthorId(user.getId());
                apCommentLike.setCommentId(dto.getCommentId());
                apCommentLike.setOperation((short)0);
                mongoTemplate.save(apCommentLike);
                apComment.setLikes(apComment.getLikes()+1);
                mongoTemplate.save(apComment);
            }else{
                Query query = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").is(dto.getCommentId()));
                mongoTemplate.remove(query,ApCommentLike.class);
                apComment.setLikes(apComment.getLikes() < 0 ? 0 : apComment.getLikes() - 1);
                mongoTemplate.save(apComment);
            }
        } finally {
            rLock.unlock();
        }


        Map map = new HashMap();
        map.put("likes",apComment.getLikes());
        return ResponseResult.okResult(map);
    }



    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        if (dto==null || dto.getArticleId()==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        if (StringUtils.isBlank(dto.getContent()) || dto.getContent().length() >140)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null || user.getId()==null )
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        try {
            Map map = greenTextScan.greeTextScan(dto.getContent());
            String suggestion = (String) map.get("suggestion");
            if ("block".equals(suggestion))
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"请谨言慎行");
        } catch (Exception e) {
            e.printStackTrace();
        }
        ApUser apuser = userFeign.findUserById(Long.valueOf(user.getId()));
        if (apuser==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN,"当前登陆信息有误");
        ApComment apComment = new ApComment();
        apComment.setAuthorId(apuser.getId());
        apComment.setAuthorName(apuser.getName());
        apComment.setEntryId(dto.getArticleId());
        apComment.setType((short)0);
        apComment.setContent(dto.getContent());
        apComment.setImage(apuser.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short)0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        mongoTemplate.save(apComment);


        return ResponseResult.okResult();
    }
}
